// 文件路径: src/main/java/com/macro/mall/tiny/modules/oms/service/impl/UserServiceImpl.java
package com.macro.mall.tiny.modules.oms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.macro.mall.tiny.modules.oms.dto.UserListQueryParam;
import com.macro.mall.tiny.modules.oms.dto.UserLoginParam;
import com.macro.mall.tiny.modules.oms.dto.UserParam;
import com.macro.mall.tiny.modules.oms.dto.UserUpdateParam;
import com.macro.mall.tiny.modules.oms.mapper.UserMapper;
import com.macro.mall.tiny.modules.oms.model.User;
import com.macro.mall.tiny.modules.oms.service.UserService;
import com.macro.mall.tiny.security.util.JwtTokenUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;

/**
 * <p>
 * 顾客表 服务实现类
 * </p>
 *
 * @author macro
 * @since 2023-11-07
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.expiration}")
    private Long expiration;

    @Override
    public String login(UserLoginParam loginParam) {
        String phone = loginParam.getPhone();
        String password = loginParam.getPassword();

        // 根据手机号获取用户
        User user = getByPhone(phone);
        if (user == null) {
            return null;
        }

        // 检查用户状态
        if (user.getStatus() == 0) {
            return null;
        }

        // 验证密码
        if (!passwordEncoder.matches(password, user.getPassword())) {
            return null;
        }

        // 生成token
        if (user.getUserId() == null || user.getPhone() == null) {
            return null;
        }
        
        // 创建UserDetails实现类用于生成token
        UserDetails userDetails = org.springframework.security.core.userdetails.User
            .withUsername(user.getUserId().toString())
            .password(user.getPassword())
            .authorities("USER")
            .build();
            
        return jwtTokenUtil.generateToken(userDetails);
    }

    @Override
    public void logout(String token) {
        // 在实际应用中，可能需要将token加入黑名单
        // 这里简化处理，不做任何操作
    }

    @Override
    public User getUserInfo(Integer userId) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUserId, userId)
                .eq(User::getDelFlag, 0);
        return getOne(wrapper);
    }

    @Override
    public boolean updateUserInfo(Integer userId, UserUpdateParam updateParam) {
        // 如果提供了新的电话号码，检查是否已被其他用户使用
        if (updateParam.getPhone() != null && !updateParam.getPhone().isEmpty()) {
            User existingUser = getByPhone(updateParam.getPhone());
            // 如果找到的用户不是当前用户，则说明电话号码已被占用
            if (existingUser != null && !existingUser.getUserId().equals(userId)) {
                return false; // 电话号码已被其他用户使用
            }
        }
        
        User user = new User();
        // 手动复制非null属性，避免覆盖密码字段
        if (updateParam.getName() != null) {
            user.setName(updateParam.getName());
        }
        if (updateParam.getBranch() != null) {
            user.setBranch(updateParam.getBranch());
        }
        if (updateParam.getSex() != null) {
            user.setSex(updateParam.getSex());
        }
        if (updateParam.getStatus() != null) {
            user.setStatus(updateParam.getStatus());
        }
        if (updateParam.getPhone() != null) {
            user.setPhone(updateParam.getPhone());
        }
        // 如果提供了新密码，则进行加密处理
        if (updateParam.getPassword() != null && !updateParam.getPassword().isEmpty()) {
            user.setPassword(passwordEncoder.encode(updateParam.getPassword()));
        }
        
        user.setUserId(userId);
        user.setUpdatedAt(LocalDateTime.now());
        return updateById(user);
    }

    @Override
    public User getByPhone(String phone) {
        return userMapper.getByPhone(phone);
    }

    @Override
    public User getByName(String name) {
        return userMapper.getByName(name);
    }

    @Override
    public boolean create(UserParam userParam) {
        // 检查手机号是否已存在
        User existingUser = getByPhone(userParam.getPhone());
        if (existingUser != null) {
            return false;
        }

        User user = new User();
        BeanUtils.copyProperties(userParam, user);
        user.setPassword(passwordEncoder.encode(userParam.getPassword()));
        user.setStatus(1); // 默认启用
        user.setDelFlag(0); // 正常状态
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        return save(user);
    }
    
    @Override
    public Page<User> pageList(UserListQueryParam queryParam) {
        Page<User> page = new Page<>(queryParam.getPageNum(), queryParam.getPageSize());
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getDelFlag, 0);

        // 关键字搜索
        if (StringUtils.hasText(queryParam.getKeywords())) {
            wrapper.and(w -> w.like(User::getPhone, queryParam.getKeywords())
                    .or()
                    .like(User::getName, queryParam.getKeywords())
                    .or()
                    .like(User::getBranch, queryParam.getKeywords())
            );
        }
        
        // 状态筛选
        if (queryParam.getStatus() != null) {
            wrapper.eq(User::getStatus, queryParam.getStatus());
        }

        wrapper.orderByDesc(User::getCreatedAt);
        return page(page, wrapper);
    }
    
    @Override
    public boolean delete(Integer userId) {
        User user = new User();
        user.setUserId(userId);
        user.setDelFlag(1);
        user.setUpdatedAt(LocalDateTime.now());
        return updateById(user);
    }
}
